// Package models 模型通用属性和方法
package models

import (
	"fmt"
	"time"

	"database/sql/driver"

	"github.com/spf13/cast"
	"gorm.io/gorm"
)

// BaseModel 模型基类
type BaseModel struct {
	ID uint64 `gorm:"column:id;primaryKey;autoIncrement;" json:"id,omitempty"`
}

// CommonTimestampsField 时间戳
type CommonTimestampsField struct {
	DeletedAt gorm.DeletedAt `gorm:"nullable;column:deleted_at;comment:删除时间;type:timestamp;index;" json:"deleted_at"  form:"deleted_at"  db:"deleted_at"`
	CreatedAt FormatTime     `gorm:"default:CURRENT_TIMESTAMP;column:created_at;comment:创建时间;type:timestamp;index;" json:"created_at"  form:"created_at"  db:"created_at"`
	UpdatedAt FormatTime     `gorm:"default:CURRENT_TIMESTAMP;column:updated_at;comment:更新时间;type:timestamp;index;" json:"updated_at"  form:"updated_at"  db:"updated_at"`
}

func (a BaseModel) GetStringID() string {
	return cast.ToString(a.ID)
}

// https://blog.csdn.net/glenshappy/article/details/120890448
// 1. 创建 time.Time 类型的副本 FormatTime
type FormatTime struct {
	time.Time
}

// 2. 为 Xtime 重写 MarshaJSON 方法，在此方法中实现自定义格式的转换；
func (t FormatTime) MarshalJSON() ([]byte, error) {
	output := fmt.Sprintf("\"%s\"", t.Format("2006-01-02 15:04:05"))
	return []byte(output), nil
}

// 3. 为 Xtime 实现 Value 方法，写入数据库时会调用该方法将自定义时间类型转换并写入数据库；
func (t FormatTime) Value() (driver.Value, error) {
	var zeroTime time.Time
	if t.Time.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return t.Time, nil
}

// 4. 为 Xtime 实现 Scan 方法，读取数据库时会调用该方法将时间数据转换成自定义时间类型；
func (t *FormatTime) Scan(v interface{}) error {
	value, ok := v.(time.Time)
	if ok {
		*t = FormatTime{Time: value}
		return nil
	}
	return fmt.Errorf("can not convert %v to timestamp", v)
}
